package com.xuecheng.base.util;

import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 用于将视频文件转换为 MP4 格式的工具类
 */
@Slf4j
public class Mp4VideoUtil extends VideoUtil {

    /**
     * ffmpeg 的路径
     */
    private final String ffmpegPath;

    /**
     * 源视频文件路径
     */
    private final String videoPath;

    /**
     * 转换后的 MP4 文件名
     */
    private final String mp4Name;

    /**
     * 转换后的 MP4 文件存放目录
     */
    private final String mp4FolderPath;

    /**
     * 构造函数，用于初始化 Mp4VideoUtil 对象
     *
     * @param ffmpegPath    ffmpeg 的路径
     * @param videoPath     源视频文件路径
     * @param mp4Name       转换后的 MP4 文件名
     * @param mp4FolderPath 转换后的 MP4 文件存放目录
     */
    public Mp4VideoUtil(String ffmpegPath, String videoPath, String mp4Name, String mp4FolderPath) {
        super(ffmpegPath);
        this.ffmpegPath = ffmpegPath;
        this.videoPath = videoPath;
        this.mp4Name = mp4Name;
        this.mp4FolderPath = mp4FolderPath;
    }

    /**
     * 清除已生成的 MP4 文件
     *
     * @param mp4Path MP4 文件路径
     */
    private void clearMp4(String mp4Path) {
        File mp4File = new File(mp4Path);
        if (mp4File.exists() && mp4File.isFile()) {
            boolean deleted = mp4File.delete();
            if (!deleted) log.error("删除MP4文件失败，路径: {}", mp4Path);
        }
    }

    /**
     * 视频编码，生成 MP4 文件
     *
     * @return 成功返回 "success"，转换失真返回控制台日志，有异常返回 "error"
     */
    public String generateMp4() {
        // 1. 清除已生成的 MP4 文件
        clearMp4(mp4FolderPath + mp4Name);
        // 2. 构建 FFmpeg 命令
        List<String> command = buildCommand();
        // 3. 执行 FFmpeg 命令，获取输出结果
        String output;
        try {
            ProcessBuilder builder = new ProcessBuilder(command);
            builder.redirectErrorStream(true); // 合并标准输入流和错误输入流
            Process process = builder.start();
            output = waitForProcess(process); // 获取进程输出
        } catch (Exception ex) {
            log.error("视频编码为mp4文件失败：{}", ex.getMessage());
            return "error: " + ex.getMessage();
        }
        // 检查生成的 MP4 文件时长是否与源文件一致
        boolean isVideoTimeValid = checkVideoTime(videoPath, mp4FolderPath + mp4Name);
        if (!isVideoTimeValid) return output; // 时长不一致，返回控制台日志
        else return "success"; // 转换成功
    }

    /**
     * 构建 FFmpeg 命令
     *
     * @return FFmpeg 命令列表
     */
    private List<String> buildCommand() {
        List<String> command = new ArrayList<>();
        command.add(ffmpegPath);
        command.add("-i");
        command.add(videoPath);
        command.add("-c:v");
        command.add("libx264");
        command.add("-y"); // 覆盖输出文件
        command.add("-s");
        command.add("1280x720");
        command.add("-pix_fmt");
        command.add("yuv420p");
        command.add("-b:a");
        command.add("63k");
        command.add("-b:v");
        command.add("753k");
        command.add("-r");
        command.add("18");
        command.add(mp4FolderPath + mp4Name);
        return command;
    }

    /**
     * 主函数，用于测试 Mp4VideoUtil 类
     *
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        // ffmpeg 的路径
        String ffmpegPath = "D:\\soft\\FFmpeg\\ffmpeg\\ffmpeg.exe";
        // 源视频路径
        String videoPath = "E:\\学成在线\\学成在线项目—资料\\upload\\视频\\转换.avi";
        // 转换后的 MP4 文件名
        String mp4Name = "转换.mp4";
        // 转换后的 MP4 文件存放目录
        String mp4FolderPath = "E:\\学成在线\\学成在线项目—资料\\upload\\视频\\";
        // 创建工具类对象
        Mp4VideoUtil videoUtil = new Mp4VideoUtil(ffmpegPath, videoPath, mp4Name, mp4FolderPath);
        // 开始视频转换，成功将返回 "success"
        String result = videoUtil.generateMp4();
        System.out.println(result);
    }
}